//
//  AppLogManager.swift
//  XiaoweHealthy
//
//  Created by Riven on 2022/4/9.
//

import Foundation
import ZIPFoundation
import CocoaLumberjack
import AudiowiseBluetoothLib
import XCGLogger

let log = XCGLogger.default

class AppLogManager {
    
    private static let logDirName = "XWHLog"
    private static let logName = "XWMYLog"
    
    private static var cachesDirectoryUrl: URL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]

    private static var logDir: URL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0].appendingPathComponent(logDirName, isDirectory: true)
    private static var logSufix = "-log.log"
    static var logFileURL: URL {
        //日志文件地址
        let cachePath = logDir
//        let logName = Date().string(withFormat: "yyyy-MM-dd") + logSufix
        let logName = logName + logSufix
        let logURL = cachePath.appendingPathComponent(logName)
        
        return logURL
    }
    
    class func configLog() {
        var logLevel: XCGLogger.Level = .debug
        var ddLevel: DDLogLevel = .debug
        #if DEBUG
        #else
        if isReleaseService {
            logLevel = .info
            ddLevel = .info
        }
        #endif
        
        SQLogManager.sharedInstance().switch(ddLevel)
        SQLogManager.sharedInstance().addOSLogger()
        SQLogManager.sharedInstance().addFileLogger()
        
        createLogDir()
        
        let showLogIdentifier: Bool = false
        let showFunctionName: Bool = true
        let showThreadName: Bool = false
        let showLevel: Bool = true
        let showFileNames: Bool = true
        let showLineNumbers: Bool = true
        let showDate: Bool = true
        let fileLevel: XCGLogger.Level = logLevel
        let appendMarker: String = "\n----\n-- ** ** ** -- 分隔线 -- ** ** ** --\n----\n"
        
        if let standardConsoleDestination = log.destination(withIdentifier: XCGLogger.Constants.baseConsoleDestinationIdentifier) as? ConsoleDestination {
            standardConsoleDestination.showLogIdentifier = showLogIdentifier
            standardConsoleDestination.showFunctionName = showFunctionName
            standardConsoleDestination.showThreadName = showThreadName
            standardConsoleDestination.showLevel = showLevel
            standardConsoleDestination.showFileName = showFileNames
            standardConsoleDestination.showLineNumber = showLineNumbers
            standardConsoleDestination.showDate = showDate
            standardConsoleDestination.outputLevel = logLevel
        }
         
        let fileDesId = XCGLogger.Constants.fileDestinationIdentifier
        log.remove(destinationWithIdentifier: fileDesId)

        // We've been passed a file to use for logging, set up a file logger
        let maxFileSize: UInt64 = 4 * 1024 * 1024
//        let maxFileSize: UInt64 = 1024
        let maxTimeInterval: TimeInterval = 60 * 60 * 24 * 7
        let standardFileDestination = AutoRotatingFileDestination(writeToFile: logFileURL, identifier: fileDesId, shouldAppend: true, appendMarker: appendMarker, maxFileSize: maxFileSize, maxTimeInterval: maxTimeInterval, targetMaxLogFiles: 4)

        standardFileDestination.showLogIdentifier = showLogIdentifier
        standardFileDestination.showFunctionName = showFunctionName
        standardFileDestination.showThreadName = showThreadName
        standardFileDestination.showLevel = showLevel
        standardFileDestination.showFileName = showFileNames
        standardFileDestination.showLineNumber = showLineNumbers
        standardFileDestination.showDate = showDate
        standardFileDestination.outputLevel = fileLevel
        
        log.add(destination: standardFileDestination)
        
        log.logAppDetails()
        
        DispatchQueue.global().async {
            logAppInfo()
            
            clearLogFiles()
        }
    }
    
    class func createLogDir() {
        do {
            let logDirPath = logDir.path
            var isDirectory: ObjCBool = true
            if !FileManager.default.fileExists(atPath: logDirPath, isDirectory: &isDirectory) {
                try FileManager.default.createDirectory(at: logDir, withIntermediateDirectories: true)
            }
        } catch let error {
            log.error(error)
        }
    }
    
//    class func clearLogFiles() {
//        do {
//            let logDirPath = logDir.path
//            var cFiles = try FileManager.default.contentsOfDirectory(atPath: logDirPath)
//            cFiles = cFiles.filter({ $0.hasSuffix(logSufix) }).sorted()
//            
//            var removeMax = cFiles.count - 7
//            if removeMax > 0 {
//                for i in 0 ..< removeMax {
//                    let iFile = cFiles[i]
//                    let cPath = logDirPath.appendingPathComponent(iFile)
//                    
//                    try FileManager.default.removeItem(atPath: cPath)
//                }
//            }
//            
//            if let tDDLogSufix = SQLogManager.sharedInstance().logSufix() {
//                cFiles = cFiles.filter({ $0.hasSuffix(tDDLogSufix) }).sorted()
//                removeMax = cFiles.count - 7
//                if removeMax > 0 {
//                    for i in 0 ..< removeMax {
//                        let iFile = cFiles[i]
//                        let cPath = logDirPath.appendingPathComponent(iFile)
//                        
//                        try FileManager.default.removeItem(atPath: cPath)
//                    }
//                }
//            }
//
//        } catch let error {
//            log.error(error)
//        }
//    }
    
    class func clearLogFiles() {
        do {
            let logDirPath = logDir.path
            var cFiles = try FileManager.default.contentsOfDirectory(atPath: logDirPath)
            cFiles = cFiles.filter({ !$0.hasPrefix(logName) })
            
            for iFile in cFiles {
                let cPath = logDirPath.appendingPathComponent(iFile)
                
                try FileManager.default.removeItem(atPath: cPath)
            }
            
            if let tDDLogSufix = SQLogManager.sharedInstance().logSufix() {
                cFiles = cFiles.filter({ $0.hasSuffix(tDDLogSufix) }).sorted()
                let removeMax = cFiles.count - 7
                if removeMax > 0 {
                    for i in 0 ..< removeMax {
                        let iFile = cFiles[i]
                        let cPath = logDirPath.appendingPathComponent(iFile)
                        
                        try FileManager.default.removeItem(atPath: cPath)
                    }
                }
            }

        } catch let error {
            log.error(error)
        }
    }
    
    
    private class func logAppInfo() {
        log.info("\n-------------- AppInfo --------------\n")
        
        var deviceInfo = UIDevice.current.systemName + "-" + UIDevice.current.systemVersion
        log.info(deviceInfo)
        
        deviceInfo = UIDevice.current.dc.commonDeviceName
        log.info(deviceInfo)
        
        deviceInfo = UIDevice.current.name
        log.info(deviceInfo)
        
        deviceInfo = UIDevice.current.localizedModel
        log.info(deviceInfo)
        
        deviceInfo = "UIDevice-identifierForVendor: \(UIDevice.current.identifierForVendor?.uuidString ?? "")"
        log.info(deviceInfo)
        
        // 客户端应用版本号，比如v1.0
        var appInfo = Bundle.main.appName
        log.info(appInfo)
        
        appInfo = Bundle.main.appDisplayName
        log.info(appInfo)
        
        appInfo = Bundle.main.versionNumber
        log.info(appInfo)
        
        appInfo = Bundle.main.buildNumber
        log.info(appInfo)
        
        appInfo = AppCheckAppVersion.currentVersion + AppCheckAppVersion.apiTypeName
        log.info(appInfo)
        
        appInfo = serviceApiType.curUIVersion
        log.info(appInfo + "\n")
        
        appInfo = "ApiDomain: " + serviceApiType.apiDomain
        log.info(appInfo + "\n")

        appInfo = "终端设备屏幕： \(UIScreen.main.bounds)"
        log.info(appInfo + "\n")
        
        if let sqLogDir = SQLogManager.sharedInstance().defaultLogsDirectory() {
            appInfo = "SQLogs-Dir： \(sqLogDir)"
            log.info(appInfo + "\n")
        }
        
        log.info("\n-------------- AppInfo --------------\n")
        
        
    }
    
}


// MARK: - 日志
extension AppLogManager {

    private static let zipLogDirUrl: URL = cachesDirectoryUrl.appendingPathComponent("\(logDirName).zip")
    
    @discardableResult
    class func zippingLogs() -> URL? {
        log.debug("zippingLogs zipLogDirUrl = \(zipLogDirUrl)")
        
        do {
            clearLogZip()
            
            
//            let swiftybeaverLogName = "swiftybeaver.log"
//            let swiftybeaverLogUrl = cachesDirectoryUrl.appendingPathComponent(swiftybeaverLogName)
//            let isSwiftybeaverLogExists = FileManager.default.fileExists(atPath: swiftybeaverLogUrl.path)
//            let targetUrl = logDir.appendingPathComponent(swiftybeaverLogName)
//            
//            if FileManager.default.fileExists(atPath: targetUrl.path) {
//                try FileManager.default.removeItem(at: targetUrl)
//            }
//            
//            if isSwiftybeaverLogExists {
//                try FileManager.default.copyItem(at: swiftybeaverLogUrl, to: targetUrl)
//            }
            
            // SDKLog
            var sdkTargetUrl: URL?
            if let sdkLogDirUrl = AudiowiseBluetoothLib.getLogDir() {
                let lastComponent = sdkLogDirUrl.lastPathComponent
                let targetUrl = logDir.appendingPathComponent(lastComponent)
                
                sdkTargetUrl = targetUrl
                
                var isDirectory: ObjCBool = true
                if FileManager.default.fileExists(atPath: targetUrl.path, isDirectory: &isDirectory) {
                    try FileManager.default.removeItem(at: targetUrl)
                }
                
                try FileManager.default.copyItem(at: sdkLogDirUrl, to: targetUrl)
            }
            
//            var isDDLogExists = false
//            var ddlogDirLastComponent = ""
//            if let ddlogDir = SQLogManager.sharedInstance().defaultLogsDirectory() {
//                ddlogDirLastComponent = ddlogDir.lastPathComponent;
//                if !ddlogDirLastComponent.isEmpty {
//                    let ddlogUrl = URL(fileURLWithPath: ddlogDir)
//                    
//                    var isDirectory: ObjCBool = true
//                    isDDLogExists = FileManager.default.fileExists(atPath: ddlogUrl.path, isDirectory: &isDirectory)
//                    if isDDLogExists {
//                        try FileManager.default.copyItem(at: ddlogUrl, to: logDir)
//                    }
//                }
//            }
            
            // AWLog
            let awLogName = "AWLog"
            let awLogUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent(awLogName, isDirectory: true)
            
            let awLogZipUrl = logDir.appendingPathComponent("\(awLogName).zip")

            var isDirectory: ObjCBool = true
            if FileManager.default.fileExists(atPath: awLogUrl.path, isDirectory: &isDirectory) {
                if FileManager.default.fileExists(atPath: awLogZipUrl.path) {
                    try FileManager.default.removeItem(at: awLogZipUrl)
                }
                try FileManager.default.zipItem(at: awLogUrl, to: awLogZipUrl)
            }
            
            try FileManager.default.zipItem(at: logDir, to: zipLogDirUrl, compressionMethod: .none)
            
            if let url = sdkTargetUrl {
                try FileManager.default.removeItem(at: url)
            }
            
            if FileManager.default.fileExists(atPath: awLogZipUrl.path) {
                try FileManager.default.removeItem(at: awLogZipUrl)
            }
//            if isDDLogExists, !ddlogDirLastComponent.isEmpty {
//                let ddlogTargetUrl = logDir.appendingPathComponent(ddlogDirLastComponent, isDirectory: true)
//
//                try FileManager.default.removeItem(at: ddlogTargetUrl)
//            }
            
            return zipLogDirUrl
        } catch {
            log.error("Log Zip >> Creation of ZIP archive failed with error:\(error)")
            return nil
        }
    }
    
    class func clearLogZip() {
        do {
            let isExist = FileManager.default.fileExists(atPath: zipLogDirUrl.path)
            if isExist {
                try FileManager.default.removeItem(at: zipLogDirUrl)
            }
        } catch {
            log.error("Log Zip >> Remove of ZIP archive failed with error:\(error)")
        }
    }
    
}
